package MyFramePro.Service.Impl;

import MyFramePro.Constants.SystemConstants;
import MyFramePro.Domain.Entity.*;
import MyFramePro.Domain.ResponseResult;
import MyFramePro.Domain.Vo.*;
import MyFramePro.Enums.AppHttpCodeEnum;
import MyFramePro.Exception.SystemException;
import MyFramePro.Mapper.UserMapper;
import MyFramePro.Mapper.UserRoleMapper;
import MyFramePro.Service.UserService;
import MyFramePro.Utils.BeanCopyUtils;
import MyFramePro.Utils.SecurityUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.util.function.SupplierUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private UserServiceImpl userService;

    @Resource
    private PasswordEncoder passwordEncoder;    //这里为加密相关类

    @Resource
    private UserRoleMapper userRoleMapper;

    @Resource
    private UserRoleServiceImpl userRoleService;

    @Resource
    private RoleServiceImpl roleService;

    /**
     * 这里是个人信息查询的功能
     */
    @Override
    public ResponseResult userInfo() {

        //1.从 Security 中保存的用户登录信息获取到 userId
        Long userId = SecurityUtils.getUserId();

        //2.根据 Id 查询对应的用户信息
        User user = userService.getById(userId);

        //3.根据前端所需的字段值，封装为对应的 Vo 类型
        UserInfoVo userInfoVo = BeanCopyUtils.myCopyBean(user, UserInfoVo.class);

        return ResponseResult.okResult(userInfoVo);
    }


    /**
     * 这里是修改个人信息的功能
     */
    @Override
    public ResponseResult updateInfo(User user) {

        LoginUser loginUser = SecurityUtils.getLoginUser();

        if(Objects.equals(loginUser.getUser().getId(), user.getId())) {     //使用安全框架中的当前认证的用户信息，进行二次确认
            userService.updateById(user);
        }
        return ResponseResult.okResult();
    }


    /**
     * 这里是用户注册的功能
     */
    @Override
    public ResponseResult userRegister(User user) {

        //1.对注册的信息进行非空判断
        registerInfoNotNull(user);

        //2.注册的信息在源数据中不存在，没有重复
        if(registerInfoExist(user)) {

            //3.对注册的密码进行加密
            String encodePassword = passwordEncoder.encode(user.getPassword());
            user.setPassword(encodePassword);

            //4.将注册的信息存入数据库
            userService.save(user);
        }

        return ResponseResult.okResult();
    }

    /**
     * 这里是注册信息非空判断的方法
     */
    private static void registerInfoNotNull(User user) {
        if(Objects.isNull(user.getUserName())){
            throw new SystemException(AppHttpCodeEnum.USERNAME_NOT_NULL);   //用户名
        }
        if(Objects.isNull(user.getPassword())){
            throw new SystemException(AppHttpCodeEnum.PASSWORD_NOT_NULL);   //密码
        }
        if(Objects.isNull(user.getNickName())){
            throw new SystemException(AppHttpCodeEnum.NICKNAME_NOT_NULL);   //昵称
        }
        if(Objects.isNull(user.getEmail())){
            throw new SystemException(AppHttpCodeEnum.EMAIL_NOT_NULL);  //邮箱
        }
    }


    /**
     * 这里是检验注册信息是否已经存在的方法
     */
    private boolean registerInfoExist(User user){

        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<User> queryWrapper1 = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<User> queryWrapper2 = new LambdaQueryWrapper<>();

        queryWrapper.eq(User::getUserName,user.getUserName());
        queryWrapper1.eq(User::getNickName,user.getNickName());
        queryWrapper2.eq(User::getEmail,user.getEmail());

        if(userService.count(queryWrapper)>0){
            throw new SystemException(AppHttpCodeEnum.USERNAME_EXIST);    //用户名
        }else if(userService.count(queryWrapper1)>0){
            throw new SystemException(AppHttpCodeEnum.NICKNAME_EXIST);    //昵称
        } else if(userService.count(queryWrapper2)>0){
            throw new SystemException(AppHttpCodeEnum.EMAIL_EXIST);    //邮箱
        }
        return true;
    }


    /**
     * 这里是查询用户列表的功能
     */
    @Override
    public ResponseResult selectUserList(Integer pageNum, Integer pageSize, String userName, String phonenumber, String status) {

        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        //1.可以根据用户名模糊搜索
        queryWrapper.like(StringUtils.hasText(userName),User::getUserName, userName);
        //1.1可以进行手机号的搜索
        queryWrapper.eq(StringUtils.hasText(phonenumber),User::getPhonenumber, phonenumber);
        //1.2可以进行状态的查询
        if(StringUtils.hasText(status)) {
            queryWrapper.eq(User::getStatus, status);
        }else {
            queryWrapper.eq(User::getStatus, SystemConstants.ROLE_STATUS);
        }

        List<User> userList = userService.list(queryWrapper);

        //2.进行分页
        Page<User> page = new Page<>(pageNum,pageSize);
        //2.1根据条件查询分页信息
        userService.page(page, queryWrapper);

        //3.由于前端需求字段，这里使用 Vo 类型字段进行封装
        PageVo pageVo = new PageVo(userList,page.getTotal());

        return ResponseResult.okResult(pageVo);
    }


    /**
     * 这里是新增用户的功能
     *
     * ​	注意：新增用户时注意密码加密存储。
     *
     * ​	用户名不能为空，否则提示：必需填写用户名
     *
     * ​	用户名必须之前未存在，否则提示：用户名已存在
     *
     * ​    手机号必须之前未存在，否则提示：手机号已存在
     *
     * ​	邮箱必须之前未存在，否则提示：邮箱已存在
     */
    @Override
    public ResponseResult addUser(BehindUserVo behindUserVo) {

        //1.先将用户的信息保存
        //1.1密码加密存储
        String encodePassword = passwordEncoder.encode(behindUserVo.getPassword());
        behindUserVo.setPassword(encodePassword);
        //1.2用户名不能为空，否则提示：必需填写用户名
        if(!StringUtils.hasText(behindUserVo.getUserName())){
            throw new SystemException(AppHttpCodeEnum.USERNAME_NOT_NULL);
        }
        //1.3检验注册信息是否已经存在
        User user = BeanCopyUtils.myCopyBean(behindUserVo, User.class);
        boolean exist = registerInfoExist(user);
        //1.4若当前信息之前都不存在，则进行存储用户信息
        if(exist){
            userService.save(user);
        }

        //2.然后再保存用户与角色的关联信息
        //2.1获取角色 ID
        List<Long> roleIds = behindUserVo.getRoleIds();
        //2.2获取当前用户 ID (自动生成的)
        Long userId = user.getId();
        List<UserRole> userRoleList = roleIds.stream()
                .map(new Function<Long, UserRole>() {
                    @Override
                    public UserRole apply(Long roleId) {

                        return new UserRole(userId, roleId);
                    }
                }).collect(Collectors.toList());

        userRoleService.saveBatch(userRoleList);

        return ResponseResult.okResult();
    }


    /**
     * 这里是删除用户的功能
     */
    @Override
    public ResponseResult deleteUser(Long id) {

        userService.removeById(id);

        return ResponseResult.okResult();
    }


    /**
     * 这里是修改用户的功能————回显信息
     */
    @Override
    public ResponseResult showUpateUserInfo(Long id) {

        //1.获取当前用户信息，并转换为 Vo 类型的对象
        User user = userService.getById(id);
        UserInfoVo userInfoVo = BeanCopyUtils.myCopyBean(user, UserInfoVo.class);

        //2.获取所有角色的列表
        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Role::getStatus,SystemConstants.ROLE_STATUS);
        List<Role> roleList = roleService.list(queryWrapper);

        //3.获取用户所关联的角色id列表
        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRole::getUserId,user.getId());
        List<UserRole> userRoleList = userRoleService.list(wrapper);
        ArrayList<Long> roleIds = new ArrayList<>();
        userRoleList.forEach(new Consumer<UserRole>() {
                    @Override
                    public void accept(UserRole userRole) {
                        roleIds.add(userRole.getRoleId());
                    }
                });

        //4.由于前端需求字段，这里使用 Vo 类型对象进行封装
        BehindUpdateUserListVo userListVo = new BehindUpdateUserListVo(roleList,userInfoVo,roleIds);

        return ResponseResult.okResult(userListVo);
    }


    /**
     * 这里是修改用户的功能
     */
    @Override
    public ResponseResult updateUser(BehindUserVo behindUserVo) {



        //1.先更新当前的用户信息
        Long userId = behindUserVo.getId();
        User user = BeanCopyUtils.myCopyBean(behindUserVo, User.class);
        userService.updateById(user);

        //2.删除更新之前的关联信息
        LambdaQueryWrapper<UserRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserRole::getUserId,userId);
        userRoleService.remove(queryWrapper);

        //2.1再更新当前的用户与角色的关联信息
        List<Long> roleIds = behindUserVo.getRoleIds();
        List<UserRole> userRoleList = roleIds.stream()
                .map(new Function<Long, UserRole>() {
                    @Override
                    public UserRole apply(Long roleId) {

                        return new UserRole(userId, roleId);
                    }
                }).collect(Collectors.toList());
        userRoleService.saveBatch(userRoleList);


        return ResponseResult.okResult();
    }


}
